import os
import logging
from typing import List, Optional, Dict, Any

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, BackgroundTasks
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session

from apps.meetings.models import (
    Meeting, 
    MeetingStatus,
    MeetingCreate,
    MeetingResponse,
    MeetingUpdate,
    MeetingStatisticsResponse
)
from apps.meetings.services import MeetingService, get_meeting_service
from core.database import get_db
from core.auth import get_current_active_user
from apps.users.models import User

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s'
)
logger = logging.getLogger(__name__)

# 创建路由
router = APIRouter(
    prefix="/meetings",
    tags=["meetings"],
    responses={404: {"description": "未找到"}},
)


@router.post("/", response_model=MeetingResponse)
async def create_meeting(
    meeting_create: MeetingCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    创建新会议
    
    参数:
        meeting_create: 会议创建信息
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        创建的会议信息
    """
    try:
        # 调用服务创建会议
        meeting = meeting_service.create_meeting(
            title=meeting_create.title,
            description=meeting_create.description,
            user_id=current_user.id
        )
        
        # 将数据库模型转换为响应模型
        return MeetingResponse(
            id=meeting.id,
            title=meeting.title,
            description=meeting.description,
            status=meeting.status,
            created_at=meeting.created_at,
            updated_at=meeting.updated_at,
            file_name=meeting.file_name
        )
        
    except Exception as e:
        logger.error(f"创建会议失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"创建会议失败: {str(e)}")


@router.post("/upload", response_model=MeetingResponse)
async def upload_meeting_file(
    background_tasks: BackgroundTasks,
    title: str,
    description: str = "",
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    上传会议文件并创建会议
    
    参数:
        background_tasks: 后台任务
        title: 会议标题
        description: 会议描述
        file: 上传的文件
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        创建的会议信息
    """
    try:
        # 检查文件类型
        allowed_extensions = ['.wav', '.mp3', '.m4a', '.flac', '.ogg', '.aac', '.wma']
        file_ext = os.path.splitext(file.filename)[1].lower()
        
        if file_ext not in allowed_extensions:
            raise HTTPException(
                status_code=400,
                detail=f"不支持的文件格式: {file_ext}。支持的格式: {', '.join(allowed_extensions)}"
            )
        
        # 检查文件大小 (限制500MB)
        max_size = 500 * 1024 * 1024  # 500MB
        file_content = await file.read()
        
        if len(file_content) > max_size:
            raise HTTPException(
                status_code=400,
                detail="文件大小超过限制 (500MB)"
            )
        
        # 保存文件
        import uuid
        unique_filename = f"{uuid.uuid4()}{file_ext}"
        upload_dir = os.path.join("uploads", str(current_user.id))
        os.makedirs(upload_dir, exist_ok=True)
        file_path = os.path.join(upload_dir, unique_filename)
        
        with open(file_path, "wb") as f:
            f.write(file_content)
        
        # 创建会议
        meeting = meeting_service.create_meeting(
            title=title,
            description=description,
            user_id=current_user.id,
            file_path=file_path,
            file_name=file.filename
        )
        
        # 添加后台任务处理音频
        background_tasks.add_task(process_meeting_audio_task, meeting.id, file_path, db)
        
        # 返回会议信息
        return MeetingResponse(
            id=meeting.id,
            title=meeting.title,
            description=meeting.description,
            status=meeting.status,
            created_at=meeting.created_at,
            updated_at=meeting.updated_at,
            file_name=meeting.file_name
        )
        
    except HTTPException as e:
        # 重新抛出HTTPException
        raise
    except Exception as e:
        logger.error(f"上传会议文件失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"上传会议文件失败: {str(e)}")


@router.post("/upload-with-meeting", response_model=MeetingResponse)
async def upload_file_with_meeting(
    background_tasks: BackgroundTasks,
    meeting_id: int,
    title: str,
    description: str = "",
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    上传文件到已存在的会议
    
    参数:
        background_tasks: 后台任务
        meeting_id: 会议ID
        title: 会议标题
        description: 会议描述
        file: 上传的文件
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        更新后的会议信息
    """
    try:
        # 检查会议是否存在
        meeting = meeting_service.get_meeting_by_id(meeting_id)
        if not meeting:
            raise HTTPException(status_code=404, detail="会议不存在")
        
        # 检查权限
        if meeting.created_by_id != current_user.id:
            raise HTTPException(status_code=403, detail="无权限访问此会议")
        
        # 检查文件类型
        allowed_extensions = ['.wav', '.mp3', '.m4a', '.flac', '.ogg', '.aac', '.wma']
        file_ext = os.path.splitext(file.filename)[1].lower()
        
        if file_ext not in allowed_extensions:
            raise HTTPException(
                status_code=400,
                detail=f"不支持的文件格式: {file_ext}。支持的格式: {', '.join(allowed_extensions)}"
            )
        
        # 检查文件大小 (限制500MB)
        max_size = 500 * 1024 * 1024  # 500MB
        file_content = await file.read()
        
        if len(file_content) > max_size:
            raise HTTPException(
                status_code=400,
                detail="文件大小超过限制 (500MB)"
            )
        
        # 保存文件
        import uuid
        unique_filename = f"{uuid.uuid4()}{file_ext}"
        upload_dir = os.path.join("uploads", str(current_user.id))
        os.makedirs(upload_dir, exist_ok=True)
        file_path = os.path.join(upload_dir, unique_filename)
        
        with open(file_path, "wb") as f:
            f.write(file_content)
        
        # 删除原有的文件（如果有）
        if meeting.file_path and os.path.exists(meeting.file_path):
            try:
                os.remove(meeting.file_path)
                logger.info(f"已删除原有会议文件: {meeting.file_path}")
            except Exception as e:
                logger.error(f"删除原有会议文件失败: {str(e)}")
                # 继续执行，文件删除失败不应阻止会议更新
        
        # 更新会议信息
        updated_meeting = meeting_service.update_meeting(
            meeting_id=meeting_id,
            title=title,
            description=description,
            file_path=file_path,
            file_name=file.filename,
            status=MeetingStatus.PROCESSING  # 设置为处理中状态
        )
        
        # 添加后台任务处理音频
        background_tasks.add_task(process_meeting_audio_task, meeting_id, file_path, db)
        
        # 返回更新后的会议信息
        return MeetingResponse(
            id=updated_meeting.id,
            title=updated_meeting.title,
            description=updated_meeting.description,
            status=updated_meeting.status,
            created_at=updated_meeting.created_at,
            updated_at=updated_meeting.updated_at,
            file_name=updated_meeting.file_name
        )
        
    except HTTPException as e:
        # 重新抛出HTTPException
        raise
    except Exception as e:
        logger.error(f"上传会议文件失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"上传会议文件失败: {str(e)}")


@router.get("/", response_model=List[MeetingResponse])
async def get_meetings(
    limit: int = 100,
    offset: int = 0,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    获取当前用户的会议列表
    
    参数:
        limit: 返回的会议数量上限
        offset: 偏移量
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        会议列表
    """
    try:
        # 获取用户的会议列表
        meetings = meeting_service.get_user_meetings(
            user_id=current_user.id,
            limit=limit,
            offset=offset
        )
        
        # 转换为响应模型列表
        return [
            MeetingResponse(
                id=meeting.id,
                title=meeting.title,
                description=meeting.description,
                status=meeting.status,
                created_at=meeting.created_at,
                updated_at=meeting.updated_at,
                file_name=meeting.file_name
            )
            for meeting in meetings
        ]
        
    except Exception as e:
        logger.error(f"获取会议列表失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取会议列表失败: {str(e)}")


@router.get("/{meeting_id}", response_model=MeetingResponse)
async def get_meeting(
    meeting_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    获取单个会议详情
    
    参数:
        meeting_id: 会议ID
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        会议详情
    """
    try:
        # 获取会议
        meeting = meeting_service.get_meeting_by_id(meeting_id)
        
        if not meeting:
            raise HTTPException(status_code=404, detail="会议不存在")
        
        # 检查权限（确保是用户自己的会议）
        if meeting.created_by_id != current_user.id:
            raise HTTPException(status_code=403, detail="无权限访问此会议")
        
        # 转换为响应模型
        response = MeetingResponse(
            id=meeting.id,
            title=meeting.title,
            description=meeting.description,
            status=meeting.status,
            created_at=meeting.created_at,
            updated_at=meeting.updated_at,
            file_name=meeting.file_name
        )
        
        # 如果有转录结果，添加到响应中
        if meeting.transcription_result:
            response.transcription_result = meeting.transcription_result
        
        return response
        
    except HTTPException as e:
        # 重新抛出HTTPException
        raise
    except Exception as e:
        logger.error(f"获取会议详情失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取会议详情失败: {str(e)}")


@router.put("/{meeting_id}", response_model=MeetingResponse)
async def update_meeting(
    meeting_id: int,
    meeting_update: MeetingUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    更新会议信息
    
    参数:
        meeting_id: 会议ID
        meeting_update: 会议更新信息
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        更新后的会议信息
    """
    try:
        # 获取会议
        meeting = meeting_service.get_meeting_by_id(meeting_id)
        
        if not meeting:
            raise HTTPException(status_code=404, detail="会议不存在")
        
        # 检查权限
        if meeting.created_by_id != current_user.id:
            raise HTTPException(status_code=403, detail="无权限修改此会议")
        
        # 调用服务更新会议
        updated_meeting = meeting_service.update_meeting(
            meeting_id=meeting_id,
            title=meeting_update.title,
            description=meeting_update.description
        )
        
        # 转换为响应模型
        return MeetingResponse(
            id=updated_meeting.id,
            title=updated_meeting.title,
            description=updated_meeting.description,
            status=updated_meeting.status,
            created_at=updated_meeting.created_at,
            updated_at=updated_meeting.updated_at,
            file_name=updated_meeting.file_name,
            transcription_result=updated_meeting.transcription_result
        )
        
    except HTTPException as e:
        # 重新抛出HTTPException
        raise
    except Exception as e:
        logger.error(f"更新会议信息失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"更新会议信息失败: {str(e)}")


@router.delete("/{meeting_id}", response_model=Dict[str, str])
async def delete_meeting(
    meeting_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    删除会议
    
    参数:
        meeting_id: 会议ID
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        操作结果
    """
    try:
        # 获取会议
        meeting = meeting_service.get_meeting_by_id(meeting_id)
        
        if not meeting:
            raise HTTPException(status_code=404, detail="会议不存在")
        
        # 检查权限
        if meeting.created_by_id != current_user.id:
            raise HTTPException(status_code=403, detail="无权限删除此会议")
        
        # 删除文件（如果有）
        if meeting.file_path and os.path.exists(meeting.file_path):
            try:
                os.remove(meeting.file_path)
                logger.info(f"已删除会议文件: {meeting.file_path}")
            except Exception as e:
                logger.error(f"删除会议文件失败: {str(e)}")
                # 继续执行，文件删除失败不应阻止会议删除
        
        # 调用服务删除会议
        meeting_service.delete_meeting(meeting_id)
        
        return {"message": "会议已成功删除"}
        
    except HTTPException as e:
        # 重新抛出HTTPException
        raise
    except Exception as e:
        logger.error(f"删除会议失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"删除会议失败: {str(e)}")


@router.get("/statistics", response_model=MeetingStatisticsResponse)
async def get_meeting_statistics(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    meeting_service: MeetingService = Depends(get_meeting_service)
):
    """
    获取会议统计信息
    
    参数:
        db: 数据库会话
        current_user: 当前登录用户
        meeting_service: 会议服务实例
    
    返回:
        会议统计数据
    """
    try:
        # 获取统计信息
        statistics = meeting_service.get_meeting_statistics(current_user.id)
        
        return MeetingStatisticsResponse(**statistics)
        
    except Exception as e:
        logger.error(f"获取会议统计信息失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取会议统计信息失败: {str(e)}")


async def process_meeting_audio_task(meeting_id: int, audio_path: str, db: Session):
    """
    处理会议音频的后台任务
    
    参数:
        meeting_id: 会议ID
        audio_path: 音频文件路径
        db: 数据库会话
    """
    try:
        logger.info(f"开始处理会议音频（后台任务）: {meeting_id}")
        
        # 获取会议服务实例
        meeting_service = MeetingService(db)
        
        # 调用异步处理方法
        await meeting_service.process_meeting_audio_async(meeting_id, audio_path)
        
        logger.info(f"会议音频处理完成（后台任务）: {meeting_id}")
        
    except Exception as e:
        logger.error(f"处理会议音频后台任务失败: {str(e)}")
        # 这里不抛出异常，因为后台任务的异常不会影响API响应